home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------
-
- AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
- Mail Service Access Module
-
- written by Steve Falkenburg-- MacDTS
- ©1991-1993 Apple Computer, Inc.
-
- --------------
- change history
- --------------
-
- SJF 02/19/93 update for beta build b1
- SJF 02/19/93 update for beta build b1
- SJF 10/29/92 update to a11 a11
- SJF 06/08/92 update to a8 a8
- SJF 02/15/92 first working version a4.5
- SJF 10/16/91 initial coding a3
-
- ---------------------------------------------------------------------*/
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __OCE__
- #include <OCE.h>
- #endif
-
- #ifndef __OCEMAIL__
- #include <OCEMail.h>
- #endif
-
- #include <string.h>
-
- #include "const.h"
- #include "gwerrors.h"
- #include "mytypes.h"
- #include "globals.h"
- #include "utils.h"
- #include "spoolsystem.h"
- #include "gatewaystuff.h"
- #include "spooltoaoce.h"
-
- #define kDefaultSubject "<no subject>"
- #define kDefaultSubjectLength 12
- #define kDefaultBody "<no message>"
- #define kDefaultBodyLength 12
-
- #define kMaxRStringPostIt kRString32Size-4 // maximum length of sender, subject in postit
- #define kLetterCreator 'lap2'
-
-
- // SpoolIntoAOCE
- //
- // this function is called to retrieve an external message from the spool area and submit
- // it into the incoming queue via the toolbox. it first creates a post-it for the message
- // and then creates the actual message and inserts the message data. if we wanted to be an
- // "on-line" gateway, we would just create the post-it and not the message. we would then get
- // a message opened eppc when the user double-clicked and would have to download the message
- // in response.
- //
- OSErr SpoolIntoAOCE(FSSpec *spoolSpec,SlotSpec *slot)
- {
- OSErr err;
- MSAMParam gwp;
- unsigned long macSecs;
- MSAMMsgSummary postIt;
- Ptr dataBuffer;
- unsigned long bufferLen;
- RString subject;
- RecordID entitySpecifier;
- DSSpec fromAddress;
- MailMsgRef mailRef;
- long msgSeqNum;
- unsigned char *subjectOffset;
- long blockIndex,contentLength;
- short contentTypeIndex;
- OSType contentTypes[kNumContentTypes] = {kTextContent,kPictContent,kSoundContent,
- kStyledTextContent,kMovieContent};
- TraceExecution("\pSpoolIntoAOCE");
-
- // allocate buffer for spooling from disk
-
- bufferLen = kMaxBufferSize;
- dataBuffer = NewPtrChk(bufferLen);
- if (MemError()!=noErr)
- return MemError();
-
-
- // get length of message data in bytes (for message summary info)
-
- contentLength = 0;
- for (blockIndex=0,err=noErr; err==noErr; blockIndex++) {
- err = kNoData;
- for (contentTypeIndex=0; (err!=noErr) && (contentTypeIndex<kNumContentTypes); contentTypeIndex++) {
- err = GetSpoolLength(spoolSpec,contentTypes[contentTypeIndex],kContentCreator,blockIndex,&bufferLen);
- if (err==noErr)
- contentLength += bufferLen;
- }
- }
-
- // ********** create the post-it (msg summary) for the message **************************
-
- ClearBuffer(&postIt,sizeof(MSAMMsgSummary));
- postIt.version = kMailMsgSummaryVersion;
- postIt.masterData.attrMask.sendTimeStamp = true;
- postIt.masterData.attrMask.indications = true;
- postIt.masterData.attrMask.from = true;
- postIt.masterData.attrMask.subject = true;
- postIt.masterData.attrMask.msgType = true;
- postIt.masterData.attrMask.msgFamily = true;
-
- GetDateTime(&macSecs); // time
- MacToMailTime(macSecs,&postIt.coreData.sendTime);
- *(long *)&postIt.coreData.letterIndications = 0;
- postIt.coreData.letterIndications.priority = kIPMNormalPriority; // indications
- postIt.coreData.letterIndications.hasContent = true; // true since we have cont.
- postIt.coreData.messageType.msgType = kMailLtrMsgType; // message type
- postIt.coreData.messageType.msgCreator = kLetterCreator; // message creator
- postIt.coreData.messageFamily = kMailFamily; // family of message
- postIt.coreData.messageSize = contentLength; // size of message
- postIt.coreData.addressedToMe = kAddressedAs_TO; // we faked this...
-
- // get subject
-
- bufferLen = sizeof(RString);
- err = GetFromSpool(spoolSpec,kSubjectType,kAttribCreator,0,(Ptr)&subject,&bufferLen,0);
- if (err!=noErr)
- OCECToRString(kDefaultSubject,smRoman,(RStringPtr)&subject,kRStringMaxBytes);
- OCECopyFitRString((RStringPtr)&subject,(RStringPtr)&postIt.coreData.subject,kMaxRStringPostIt);
-
- // get from name
-
- bufferLen = kMaxBufferSize;
- err = GetFromSpool(spoolSpec,kFromType,kAddrCreator,0,dataBuffer,&bufferLen,0);
- if (err!=noErr) {
- DisposPtrChk(dataBuffer);
- return err;
- }
- OCEUnpackDSSpec((PackedDSSpec*)dataBuffer,&fromAddress,&entitySpecifier);
- OCECopyFitRString(entitySpecifier.local.recordName,(RStringPtr)&postIt.coreData.sender,kMaxRStringPostIt);
-
- // move subject flush with sender RString (pack them together as close as possible even pad)
-
- subjectOffset = ((unsigned char *)&postIt.coreData.sender)+postIt.coreData.sender.dataLength+sizeof(long);
- if ((unsigned long)subjectOffset % 2)
- subjectOffset++;
- BlockMove(&postIt.coreData.subject,subjectOffset,postIt.coreData.subject.dataLength+sizeof(long));
-
- // make the message summary
-
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.pmsamCreateMsgSummary.inQueueRef = slot->inQueue;
- gwp.pmsamCreateMsgSummary.msgSummary = &postIt;
- gwp.pmsamCreateMsgSummary.buffer = nil;
- PMSAMCreateMsgSummary(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- DisposPtrChk(dataBuffer);
- return err;
- }
- msgSeqNum = gwp.pmsamCreateMsgSummary.seqNum;
-
- // ********** create the message (submit the actual data **************************
-
- // check to see if we have bcc recipients
-
-
- // first, really create the messsage
-
- bufferLen = kMaxBufferSize;
- err = GetFromSpool(spoolSpec,kBCCType,kAddrCreator,0,dataBuffer,&bufferLen,0);
- gwp.msamCreate.bccRecipients = (err==noErr); // do we have bcc recipients?
- gwp.msamCreate.queueRef = slot->inQueue;
- gwp.msamCreate.seqNum = msgSeqNum;
- gwp.msamCreate.asLetter = true;
- gwp.msamCreate.msgType.format = kIPMOSFormatType;
- gwp.msamCreate.msgType.theType.msgOSType.msgCreator = kLetterCreator;
- gwp.msamCreate.msgType.theType.msgOSType.msgType = kMailLtrMsgType;
- gwp.msamCreate.tunnelForm = false;
- MSAMCreate(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- DisposPtrChk(dataBuffer);
- return err;
- }
- mailRef = gwp.msamCreate.newRef;
-
- // add the time
-
- gwp.msamPutAttribute.mailMsgRef = mailRef;
- gwp.msamPutAttribute.attrID = kMailSendTimeStampBit;
- gwp.msamPutAttribute.buffer.buffer = (Ptr)&postIt.coreData.sendTime;
- gwp.msamPutAttribute.buffer.bufferSize = sizeof(MailTime);
- MSAMPutAttribute(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- // add the message family
-
- gwp.msamPutAttribute.mailMsgRef = mailRef;
- gwp.msamPutAttribute.attrID = kMailMsgFamilyBit;
- gwp.msamPutAttribute.buffer.buffer = (Ptr)&postIt.coreData.messageFamily;
- gwp.msamPutAttribute.buffer.bufferSize = sizeof(OSType);
- MSAMPutAttribute(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- // add the indications
-
- gwp.msamPutAttribute.mailMsgRef = mailRef;
- gwp.msamPutAttribute.attrID = kMailIndicationsBit;
- gwp.msamPutAttribute.buffer.buffer = (Ptr)&postIt.coreData.letterIndications;
- gwp.msamPutAttribute.buffer.bufferSize = sizeof(MailIndications);
- MSAMPutAttribute(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- // add the recipients
-
- err = AddTheRecipients(mailRef,spoolSpec,kFromType,kMailFromBit,dataBuffer,kMaxBufferSize);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- err = AddTheRecipients(mailRef,spoolSpec,kToType,kMailToBit,dataBuffer,kMaxBufferSize);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- err = AddTheRecipients(mailRef,spoolSpec,kCCType,kMailCcBit,dataBuffer,kMaxBufferSize);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- err = AddTheRecipients(mailRef,spoolSpec,kBCCType,kMailBccBit,dataBuffer,kMaxBufferSize);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- // add the subject
-
- gwp.msamPutAttribute.mailMsgRef = mailRef;
- gwp.msamPutAttribute.attrID = kMailSubjectBit;
- gwp.msamPutAttribute.buffer.buffer = (Ptr)&subject;
- gwp.msamPutAttribute.buffer.bufferSize = subject.dataLength+4;
- if ((gwp.msamPutAttribute.buffer.bufferSize%2)!=0)
- gwp.msamPutAttribute.buffer.bufferSize++;
- MSAMPutAttribute(&gwp,true);
- err = WaitPBDone(&gwp);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- // add content
-
- err = SpoolContentsToAOCE(spoolSpec,mailRef,dataBuffer);
- if (err!=noErr) {
- BailOnSubmit(mailRef,msgSeqNum,slot->inQueue,dataBuffer);
- return err;
- }
-
- // submit the letter
-
- gwp.msamSubmit.mailMsgRef = mailRef;
- gwp.msamSubmit.submitFlag = true; // submit letter
- err = MSAMSubmit(&gwp);
-
- DisposPtrChk(dataBuffer);
-
- if (err!=noErr) {
- /* delete post-it */
-
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.msamDelete.queueRef = slot->inQueue;
- gwp.msamDelete.seqNum = msgSeqNum;
- gwp.msamDelete.msgOnly = false;
- gwp.msamDelete.result = noErr; // server gw only
- MSAMDelete(&gwp,true);
- WaitPBDone(&gwp);
- }
-
- return err;
- }
-
-
- void BailOnSubmit(MailMsgRef mailRef,long seqNum,MSAMQueueRef queueRef,Ptr dataBuffer)
- {
- MSAMParam gwp;
-
- TraceExecution("\pbail out");
-
- /* delete message */
-
- DisposPtrChk(dataBuffer);
- gwp.msamSubmit.mailMsgRef = mailRef;
- gwp.msamSubmit.submitFlag = false; // abort letter
- MSAMSubmit(&gwp);
-
- /* delete post-it */
-
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.msamDelete.queueRef = queueRef;
- gwp.msamDelete.seqNum = seqNum;
- gwp.msamDelete.msgOnly = false;
- gwp.msamDelete.result = noErr; // server gw only
- MSAMDelete(&gwp,true);
- WaitPBDone(&gwp);
- }
-
-
- OSErr AddTheRecipients(MailMsgRef mailRef,FSSpec *spoolSpec,OSType recipType,MailAttributeID attrID,Ptr dataBuffer,unsigned long bufferLen)
- {
- OSErr err;
- Boolean moreRecipients = true;
- short index;
- unsigned long gotLength;
- DSSpec recipient;
- RecordID entitySpecifier;
- MSAMParam gwp;
-
- index = 0;
-
- do {
-
- gotLength = bufferLen;
- err = GetFromSpool(spoolSpec,recipType,kAddrCreator,index,dataBuffer,&gotLength,0);
- if (err==noErr && gotLength>0) {
-
- // submit one recipient
-
- OCEUnpackDSSpec((PackedDSSpec*)dataBuffer,&recipient,&entitySpecifier);
- gwp.msamPutRecipient.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.msamPutRecipient.mailMsgRef = mailRef;
- gwp.msamPutRecipient.attrID = attrID;
- gwp.msamPutRecipient.recipient = &recipient;
- gwp.msamPutRecipient.responsible = false; // always false for PMSAMs
- MSAMPutRecipient(&gwp,true);
- err = WaitPBDone(&gwp);
-
- }
- else {
- moreRecipients = false;
- err = noErr;
- }
-
- index++;
- } while (err==noErr && moreRecipients);
-
- return err;
- }
-
-
- OSErr SpoolContentsToAOCE(FSSpec *spoolSpec,MailMsgRef mailRef,Ptr dataBuffer)
- {
- long blockIndex,blockOffset;
- unsigned long bufferLen;
- OSType contentType;
- Boolean contentSpooled,startOfBlock;
- MSAMParam gwp;
- OSErr err,err2;
-
- gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
- gwp.msamPutContent.mailMsgRef = mailRef;
- gwp.msamPutContent.textScrap = nil;
- gwp.msamPutContent.buffer.buffer = dataBuffer;
- gwp.msamPutContent.script = smRoman;
-
- blockIndex = 0;
- contentType = kTextContent;
- contentSpooled = false;
- startOfBlock = true;
-
- // for each segment block...
- do {
- blockOffset = 0;
-
- // for each piece of a segment block
- do {
- bufferLen = kMaxBufferSize;
- err = GetFromSpool(spoolSpec,contentType,kContentCreator,blockIndex,
- dataBuffer,&bufferLen,blockOffset);
-
- // set up parameter block
-
- if (startOfBlock) {
- switch (contentType) {
- case kTextContent:
- gwp.msamPutContent.segmentType = kMailTextSegmentType;
- if (blockIndex==0)
- gwp.msamPutContent.startNewScript = true;
- break;
- case kPictContent:
- gwp.msamPutContent.segmentType = kMailPictSegmentType;
- break;
- case kSoundContent:
- gwp.msamPutContent.segmentType = kMailSoundSegmentType;
- break;
- case kStyledTextContent:
- gwp.msamPutContent.segmentType = kMailStyledTextSegmentType;
- if (blockIndex==0)
- gwp.msamPutContent.startNewScript = true;
- break;
- case kMovieContent:
- gwp.msamPutContent.segmentType = kMailMovieSegmentType;
- break;
- }
- }
- gwp.msamPutContent.append = !startOfBlock;
- gwp.msamPutContent.buffer.bufferSize = bufferLen;
-
- // make putcontent call
-
- if ((err==noErr)||(err==kMoreData)) {
- MSAMPutContent(&gwp,true);
- err2 = WaitPBDone(&gwp);
- if (err2!=noErr)
- return err;
- contentSpooled = true; // we spooled some content (don't need default text)
- }
-
- blockOffset += bufferLen; // increment block offset
- startOfBlock = false; // we're not at the start of a block
-
- } while (err==kMoreData);
-
- blockIndex++; // increment block index
- startOfBlock = true; // we're at the start of a block again
-
- } while (err!=noErr);
-
- if (err==kNoData)
- err = noErr;
-
- // if no content was spooled, spool some default content so AOCE will accept the letter
-
- if (contentSpooled==false) {
- strcpy(dataBuffer,kDefaultBody);
- gwp.msamPutContent.segmentType = kMailTextSegmentType;
- gwp.msamPutContent.append = false;
- gwp.msamPutContent.buffer.bufferSize = strlen(kDefaultBody);
- MSAMPutContent(&gwp,true);
- err = WaitPBDone(&gwp);
- }
-
- return err;
- }
-